package com.itlong.cloud.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.zxing.BarcodeFormat;
import com.itlong.cloud.POJO.DTO.app.AppGetVisitPassWordDTO;
import com.itlong.cloud.POJO.DTO.app.AppGetVisitorRecordPageDTO;
import com.itlong.cloud.POJO.DTO.app.MiniGetReservationProofPageDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.app.*;
import com.itlong.cloud.POJO.VO.property.PropertyQrcodeValidVO;
import com.itlong.cloud.POJO.VO.property.VisitorQrcodeVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.app.dao.IAppDeviceDao;
import com.itlong.cloud.app.dao.IAppVisitorPassCodeRecordDao;
import com.itlong.cloud.app.service.IAppDeviceService;
import com.itlong.cloud.app.service.IAppVisitorPassCodeRecordService;
import com.itlong.cloud.commons.dao.ICloudElevatorDao;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.property.dao.IPropertyEquipDao;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.DesEncryptUtil;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.picture.QrcodeUtils;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.random.RandomUtil;
import com.itlong.cloud.utils.string.StringUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.security.NoSuchProviderException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * <desc>
 *      APP访客密码通行记录业务处理接口实现类
 * </desc>
 *
 * @createDate 2017/10/30
 */
@Service
@RefreshScope
public class AppVisitorPassCodeRecordServiceImpl implements IAppVisitorPassCodeRecordService{
    private static final Logger LOG = LoggerFactory.getLogger(AppVisitorPassCodeRecordServiceImpl.class);
    @Autowired
    IAppVisitorPassCodeRecordDao iAppVisitorPassCodeRecordDao;

    @Autowired
    IAppDeviceDao iAppDeviceDao;

    @Autowired
    IAppDeviceService iAppDeviceService;


    @Autowired
    ICloudElevatorDao iCloudElevatorDao;

    @Autowired
    private IPropertyEquipDao iPropertyEquipDao;

    @Autowired
    private MessageSender messageSender;

    @Autowired
    RedisService redisService;
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private Lock writeLock;
    @PostConstruct
    public void init(){
        writeLock = lock.writeLock();
    }

    @Value("${" + PlatformConstants.PROPERTY_OPERATE_MINI_CONTENT_AES_ENCRYPT_KEY + "}")
    public String propertyOperateMiniContentAesEncryptKey;

    @Value("${" + PlatformConstants.H5_VISITOR_HTML + "}")
    public String H5_VISITOR_HTML;

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;

    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;

    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;

    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;

    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;
    /**
     * <desc>
     *      保存访客通行密码记录
     * </desc>
     *
     * @param appGetVisitPassWordDTO 访客密码通行记录实体类
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/30
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public AppVisitorPassCodeRecordPO save(AppGetVisitPassWordDTO appGetVisitPassWordDTO) throws Exception {
        //LOG.info("【APP生成访客请求入参dto】:"+appGetVisitPassWordDTO.toString());
        //获取项目是否设置访客时间自定义的配置
        Map<String,Object> mapSetting = iAppDeviceDao.getVisitorTime(appGetVisitPassWordDTO.getProjectId());
        Integer visitorTime = (Integer) mapSetting.get("visitorTimeSetting");
        Integer visitorPassword = (Integer) mapSetting.get("visitorPassword");
        AppVisitorPassCodeRecordPO passPO=new AppVisitorPassCodeRecordPO();
        passPO.setResult("SUCCESS");
        PropertyQrcodeValidVO valid= null;
        if(StringUtils.isNotBlank(appGetVisitPassWordDTO.getRoomId())){
            String[] roomIds = StringHandlerUtil.splitString(appGetVisitPassWordDTO.getRoomId());
            appGetVisitPassWordDTO.setRoomId(roomIds[0]);
            valid=iAppDeviceDao.getPropertyQrocdeVliadInfo(roomIds[0]);
        }
        if(valid!=null && valid.getProjectChargeMode()==2){
            Integer count = valid.getUsableCount() != null ? valid.getUsableCount() : 0;
            if(valid.getRoomChargeMode() == 1){
                if(count<=0) {
                    passPO.setResult(count.toString());
                    return passPO;
                }else if(StringUtils.isNotBlank(appGetVisitPassWordDTO.getCountLimit()) && Integer.valueOf(appGetVisitPassWordDTO.getCountLimit()) > valid.getUsableCount()){
                    passPO.setResult(count.toString());
                    return passPO;
                }
            }else if(valid.getRoomChargeMode() == 2){
                //按有效期
                Date now = DateUtil.formatStringToDate(DateUtil.fomatDate(new Date(), DateUtil.YMDSQL), DateUtil.YMDSQL);
                Date roomDate = DateUtil.formatStringToDate(valid.getEndTime(),DateUtil.YMDSQL);
                if(roomDate.getTime() < now.getTime()){
                    passPO.setResult("TIME");
                    return passPO;
                }
            }
        }
        //如果次数为空或者大于10 默认为10
        if(StringUtils.isBlank(appGetVisitPassWordDTO.getCountLimit())){
            appGetVisitPassWordDTO.setCountLimit("1000");
        }
        passPO.setCreateTime(new Date());
        passPO.setUpdateTime(new Date());
        passPO.setIdcardKey("");
        passPO.setTemporaryAuthDeviceUniques(appGetVisitPassWordDTO.getDeviceUniques());
        if(appGetVisitPassWordDTO.getSource()==VisitorSourceTypeEnum.MINI.getType()){
            passPO.setSource(VisitorSourceTypeEnum.MINI.getType());
        }else{
            passPO.setSource(VisitorSourceTypeEnum.APP.getType());
        }
        //如果有效时间为空，默认为当前创建时间
        boolean onDay = false;
//        if(StringUtils.isNotBlank(appGetVisitPassWordDTO.getTimeLimit()) && appGetVisitPassWordDTO.getTimeLimit().length() > 4) {
//            //业务规则变动做版本兼容
//            if (StringUtils.isBlank(appGetVisitPassWordDTO.getTimeLimit())) {
//                passPO.setStartTime(passPO.getCreateTime());
//            } else {
//                passPO.setStartTime(DateUtil.parseString("yyyy-MM-dd HH:mm", appGetVisitPassWordDTO.getCreateTime()));
//            }
//        }
        if(StringUtils.isNotBlank(appGetVisitPassWordDTO.getTimeLimit()) && appGetVisitPassWordDTO.getTimeLimit().equals("0")){
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String startStr = String.format("%s%s",DateUtil.fomatDate(passPO.getCreateTime(),DateUtil.YMDSQL)," 00:00:00");
            String endStr = String.format("%s%s",DateUtil.fomatDate(passPO.getCreateTime(), DateUtil.YMDSQL)," 23:59:59");
            passPO.setStartTime(format.parse(startStr));
            passPO.setEndTime(format.parse(endStr));
            Map<String,Object> timeDifference = DateUtil.reckonDate(endStr,startStr);
            appGetVisitPassWordDTO.setTimeLimit(timeDifference.get("min")+"");
            onDay = true;
        }else if(StringUtils.isNotBlank(appGetVisitPassWordDTO.getTimeLimit())){
            passPO.setStartTime(passPO.getCreateTime());
        } else{
            if(StringUtils.isBlank(appGetVisitPassWordDTO.getTimeLimit())){
                appGetVisitPassWordDTO.setTimeLimit("1440");
            }
            passPO.setStartTime(passPO.getCreateTime());
        }
        if((appGetVisitPassWordDTO.getVisitorReservationMark()==1 || appGetVisitPassWordDTO.getTimeLimit().equals("0") || visitorTime == 2) && StringUtils.isNotBlank(appGetVisitPassWordDTO.getVisitTime())){
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String startStr = String.format("%s%s",appGetVisitPassWordDTO.getVisitTime()," 00:00:00");
            String endStr = String.format("%s%s",appGetVisitPassWordDTO.getVisitTime()," 23:59:59");
            passPO.setStartTime(format.parse(startStr));
            passPO.setEndTime(format.parse(endStr));
            if(StringUtils.isEmpty(appGetVisitPassWordDTO.getTimeLimit())){
                appGetVisitPassWordDTO.setTimeLimit("1440");
            }
        }
//        passPO.setStartTime(DateUtil.reduceCurrentTime(passPO.getStartTime(),10*60*1000));
        passPO.setPassId(LogicIdUtil.bussinessId());
        passPO.setUrl(H5_VISITOR_HTML + "?passId=" + URLEncoder.encode(DesEncryptUtil.aesEncryptSDK(passPO.getPassId(), propertyOperateMiniContentAesEncryptKey)));
        passPO.setVisitorName(appGetVisitPassWordDTO.getVisitorName());
        passPO.setVisitorPhone(appGetVisitPassWordDTO.getVisitorPhoneNumber());
        passPO.setStatus(DataStatusEnum.NORMAL.getType());
        passPO.setUserId(appGetVisitPassWordDTO.getLoginUserId());
        //获取房间号的楼栋信息
        RoomInfoPO room = null;
        if(appGetVisitPassWordDTO.getVisitorReservationMark()==1){
            room=iAppVisitorPassCodeRecordDao.getRoomBuildAndUnitInfo(appGetVisitPassWordDTO.getRoomId(), appGetVisitPassWordDTO.getProjectId(),null);
            //如果添加访客来源是小程序访客预约（包含业主和访客身份的预约）则获取受访人的userId,并后续获取受访人的设备权限等
            String intervieweeUserId = iAppVisitorPassCodeRecordDao.getUserIdbyPhoneNum(appGetVisitPassWordDTO.getIntervieweePhone());
            appGetVisitPassWordDTO.setLoginUserId(intervieweeUserId);
            //查询本项目访客二维码次数限制是否开启，若开启后则将可用次数填充至次数限制字段
            Map<String,Object> qrcodeConfigure = iPropertyEquipDao.getVisitorConfigure(appGetVisitPassWordDTO.getProjectId());
            String visitorQrCodeTimesRestrict = StringHandlerUtil.getNullOrStringForObject(qrcodeConfigure.get("visitorQrCodeTimesRestrict"));
            String visitorQrCodeUsableTimes = StringHandlerUtil.getNullOrStringForObject(qrcodeConfigure.get("visitorQrCodeUsableTimes"));
            if("1".equals(visitorQrCodeTimesRestrict)){
                appGetVisitPassWordDTO.setCountLimit(visitorQrCodeUsableTimes);
            }
        }else{
            room=iAppVisitorPassCodeRecordDao.getRoomBuildAndUnitInfo(appGetVisitPassWordDTO.getRoomId(), appGetVisitPassWordDTO.getProjectId(),appGetVisitPassWordDTO.getLoginUserId());
            passPO.setIsPushMessage(0);
        }
        StringBuffer deviceStr = new StringBuffer();
        //获取该用户在项目上所有有权限的云对讲设备
        List<Map<String,Object>> cloudAuth = iAppDeviceDao.getCloudIntercomsAuth(appGetVisitPassWordDTO.getLoginUserId(), appGetVisitPassWordDTO.getProjectId());
        AppEntranceOrCloudIntercomAuthVO cloudVO=StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.CLOUD_INTERCOM.getType(),cloudAuth);
        if(cloudVO!=null){
            for(String str : cloudVO.getDeviceIds()){
                String deviceUnique = String.format("%s%s%s",appGetVisitPassWordDTO.getProjectId(),3,str);
                deviceStr.append(String.format("%s%s",deviceUnique,","));
            }
        }
        //获取该用户在项目上所有有权限的门禁设备
        //获取用户有权限的门禁设备机号
        List<Map<String,Object>> doorAuth = iAppDeviceDao.getDoorAuth(appGetVisitPassWordDTO.getLoginUserId(), appGetVisitPassWordDTO.getProjectId());
        AppEntranceOrCloudIntercomAuthVO doorVO=StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.ENTRANCE.getType(),doorAuth);
        if(doorVO!=null){
            for(String str : doorVO.getDeviceIds()){
                String deviceUnique = String.format("%s%s%s",appGetVisitPassWordDTO.getProjectId(),2,str);
                deviceStr.append(String.format("%s%s",deviceUnique,","));
            }
        }
        //获取当前项目有权限的电梯实体类
        List<AppFloorDevicesVO> floorVos = iAppDeviceService.getFloorDevices(appGetVisitPassWordDTO.getLoginUserId(),appGetVisitPassWordDTO.getProjectId(),1);
        //处理访客的临时设备权限
        StringBuffer temporaryAuthDoor = new StringBuffer();
        StringBuffer temporaryAuthCloudTalk = new StringBuffer();
        List<AppFloorDevicesVO> elevatorTemporaryAuthList = new ArrayList<>();
        List<String> elevatorTemAutList = new ArrayList<>();
        Map<String,String> elevatorMap = new HashMap<>();
        String builds = "";
        String units = "";
        if(room!=null){
            builds = room.getBuildId();
            units = room.getUnitId();
        }
        if(StringUtils.isNotEmpty(appGetVisitPassWordDTO.getDeviceUniques())){
            Map<String,String> mainDoorElevator = new HashMap<>();
            Map<String,String> backDoorElevator = new HashMap<>();
            List<AppFloorDevicesVO> lists = iAppDeviceService.getUserTemporaryAuthFloorDevices(appGetVisitPassWordDTO.getLoginUserId(),appGetVisitPassWordDTO.getProjectId());
            String[] deviceUniqueArr = appGetVisitPassWordDTO.getDeviceUniques().split(",");
            for(String deviceUnique : deviceUniqueArr){
                Integer deviceType = Integer.parseInt(StringHandlerUtil.copySubStr(deviceUnique, 8, 1));
                switch (PropertyEquipTypeEnum.getByEquipType(deviceType)) {
                    case ENTRANCE:
                        temporaryAuthDoor.append(deviceUnique.substring(9,13)+",");
                        deviceStr.append(String.format("%s%s",deviceUnique,","));
                        break;
                    case CLOUD_INTERCOM:
                        temporaryAuthCloudTalk.append(deviceUnique.substring(9,13)+",");
                        deviceStr.append(String.format("%s%s",deviceUnique,","));
                        break;
                    case ELEVATOR:
                        String floorAuth = "";
                        if(room!=null){
                            floorAuth = Integer.valueOf(room.getRoomNum().substring(0,2)).toString();
                        }
                        for(AppFloorDevicesVO devicesVO : lists){
                            if(deviceUnique.equals(devicesVO.getDeviceUnique())){
                                elevatorTemAutList.add(deviceUnique);
                                elevatorTemporaryAuthList.add(devicesVO);
                                if(devicesVO.getLiftDoorType()==1){
                                    mainDoorElevator.put(deviceUnique.substring(9,13),devicesVO.getLiveFloor());
                                }else{
                                    backDoorElevator.put(deviceUnique.substring(9,13),devicesVO.getLiveFloor());
                                }
                                if(java.util.Arrays.asList(devicesVO.getLiveFloor().split(",")).contains(floorAuth)){
                                    elevatorMap.put(deviceUnique,devicesVO.getLiveFloor());
                                }else{
                                    //所拜访房间业主的该电梯设备没有所拜访房间的楼层权限则不拼接楼层权限
                                    int count = 0;
                                    for(AppFloorDevicesVO floorDevicesVO : floorVos){
                                        Map<String,Object> addressMap = iCloudElevatorDao.getBuildAndUnitByDeviceUnique(deviceUnique);
                                        if(floorDevicesVO.getDeviceUnique().equals(deviceUnique) &&
                                                java.util.Arrays.asList(floorDevicesVO.getLiveFloor().split(",")).contains(floorAuth) &&
                                                (addressMap!=null && !addressMap.isEmpty() && addressMap.get("unitIds").toString().contains(room.getUnitId()))){
                                            elevatorMap.put(deviceUnique,devicesVO.getLiveFloor().isEmpty()?floorAuth:devicesVO.getLiveFloor() +","+floorAuth);
                                            count++;
                                            break;
                                        }
                                    }
                                    if(count==0){
                                        elevatorMap.put(deviceUnique,devicesVO.getLiveFloor());
                                    }else{
                                        elevatorMap.put(deviceUnique,devicesVO.getLiveFloor().isEmpty()?floorAuth:devicesVO.getLiveFloor() +","+floorAuth);
                                    }
                                }
                                Map<String,Object> buildAndUnit = iCloudElevatorDao.getBuildAndUnitBySn(String.format("%s%s%s",deviceUnique.substring(0,8),"0000",deviceUnique.substring(9,deviceUnique.length())));
                                if(buildAndUnit!=null && !buildAndUnit.isEmpty()){
                                    if(StringUtils.isNotBlank(builds) && StringUtils.isNotBlank(units)){
                                        builds = String.format("%s%s%s",builds,",",buildAndUnit.get("buildId").toString());
                                        units = String.format("%s%s%s",units,",",buildAndUnit.get("unitIds").toString());
                                    }
                                }
                                break;
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
            if(!mainDoorElevator.isEmpty()){
                passPO.setMainDoorElevatorAuth(JSONArray.toJSONString(mainDoorElevator));
            }
            if(!backDoorElevator.isEmpty()){
                passPO.setBackDoorElevatorAuth(JSONArray.toJSONString(backDoorElevator));
            }
        }
        String binaryCloudAuth=null;
        String binaryEntranceAuth=null;
        if(cloudVO!=null) {
            binaryCloudAuth = StringUtils.join(cloudVO.getDeviceIds().toArray(new String[cloudVO.getDeviceIds().size()]),",");
        }
        if(doorVO!=null){
            binaryEntranceAuth = StringUtils.join(doorVO.getDeviceIds().toArray(new String[doorVO.getDeviceIds().size()]),",");
        }

        //在此处根据拜访房间的正背门来筛选相对应正背门电梯的权限
        if(StringUtils.isNotBlank(appGetVisitPassWordDTO.getRoomId())){
            String roomDoorType = iAppVisitorPassCodeRecordDao.getRoomForDoorInfo(appGetVisitPassWordDTO.getRoomId());
            if(floorVos!=null){
                for(int i=floorVos.size()-1; i >= 0; i--){
                    String liftDoorType = iAppVisitorPassCodeRecordDao.getElevatorDoorInfo(StringHandlerUtil.autlSupply(4,floorVos.get(i).getDeviceId(),"0"),appGetVisitPassWordDTO.getProjectId());
                    //如果电梯是正门
                    if(StringUtils.isNotBlank(roomDoorType) && StringUtils.isNotBlank(liftDoorType) && !roomDoorType.equals(liftDoorType)){
                        floorVos.remove(i);
                    }
                }
            }
        }
        //
        floorVos.addAll(elevatorTemporaryAuthList);

        //如果没有设备权限直接返回null
        Map<String,Object> codeResult = null;
        if(StringUtils.isNotBlank(binaryCloudAuth) || StringUtils.isNotBlank(binaryEntranceAuth) || (floorVos!=null && !floorVos.isEmpty())) {
            String[] cloudIds = StringHandlerUtil.splitString(binaryCloudAuth);   //云对讲机号
            String[] doorIds = StringHandlerUtil.splitString(binaryEntranceAuth);     //门禁机号
            StringBuilder dIds = new StringBuilder();
            //如果解析的云对讲设备机号不为空
            if (StringUtils.isNotBlank(binaryCloudAuth)&&StringUtils.isNotBlank(appGetVisitPassWordDTO.getRoomId())) {
                //获取用户对应楼栋有权限的云对讲设备的机号
                dIds.append(iAppDeviceDao.getCloudDeviceIdsForBridge(appGetVisitPassWordDTO.getProjectId(),
                        room.getBuildId(), room.getUnitId(), cloudIds) + ",");
                if(StringUtils.isNotEmpty(temporaryAuthCloudTalk.toString())){
                    dIds.append(temporaryAuthCloudTalk.toString());
                }
            }
            StringBuilder entrances = new StringBuilder();
            //如果解析的门禁设备机号不为空
            if (StringUtils.isNotBlank(binaryEntranceAuth)&&StringUtils.isNotBlank(appGetVisitPassWordDTO.getRoomId())) {
                //获取用户对应楼栋有权限的门禁设备的机号
                String notAddressDoor = iAppDeviceDao.getEntranceDeviceIdsForBridge(appGetVisitPassWordDTO.getProjectId(),
                        room.getBuildId(), room.getUnitId(), doorIds);
                entrances.append(StringUtils.isNotBlank(notAddressDoor) ? notAddressDoor : "");
                //如果有权限的门禁设备机号为空获取当前用户项目下没有设备地址的门禁设备（一卡通授权过来的设备）
                if(entrances.length() == 0){
                    entrances.append(iAppDeviceDao.getNotHaveAddressEntranceIds(doorIds,appGetVisitPassWordDTO.getProjectId()));
                }
                if(entrances.length() != 0 ){
                    if(StringUtils.isNotEmpty(temporaryAuthDoor.toString())){
                        dIds.append(temporaryAuthDoor.toString());
                    }
                    dIds.append(String.format("%s",entrances.toString()));
                }
            }else if(StringUtils.isNotBlank(binaryEntranceAuth)&&StringUtils.isBlank(appGetVisitPassWordDTO.getRoomId())){
                if(StringUtils.isNotEmpty(temporaryAuthDoor.toString())){
                    dIds.append(temporaryAuthDoor.toString());
                }
            }
            //为了防止门禁与云对讲机号重复，现对设备机号进行去重处理
            String[] allDeviceIds = StringHandlerUtil.splitString(dIds.toString());
            Set<String> setDeviceIds = new HashSet<>();
            String deviceIds = "";
            for (String deviceId : allDeviceIds) {
                if (!deviceId.equals("null") && setDeviceIds.add(deviceId)) {
                    deviceIds += deviceId + ",";
                }
            }
            //设置门禁的id
            passPO.setDeviceId(StringUtils.isNotBlank(deviceIds) ? deviceIds.substring(0, deviceIds.length() - 1) : "");
            passPO.setUseNum(0);
            //获取项目二维码长度
            Integer codeLength = iAppDeviceDao.getCodeLength(appGetVisitPassWordDTO.getProjectId());
            //生成二维码信息
            if(appGetVisitPassWordDTO.getTimeLimit().length() > 4){
                if((valid != null && valid!=null && valid.getProjectChargeMode() == 2) || visitorTime == 1){
                    //新二维码格式
                    codeResult = this.getNewQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                            appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(),
                            Integer.valueOf(appGetVisitPassWordDTO.getTimeLimit()), elevatorTemAutList,elevatorMap, appGetVisitPassWordDTO.getCountLimit());
                }else {
                    codeResult = this.getQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                            appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(), null, elevatorTemAutList, elevatorMap);
                    if(codeLength != null && codeResult.get("qrcode").toString().toUpperCase().length() >= codeLength * 2){
                        codeResult = this.getNewQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                                appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(), Integer.valueOf(appGetVisitPassWordDTO.getTimeLimit()),
                                elevatorTemAutList, elevatorMap, appGetVisitPassWordDTO.getCountLimit());
                    }
                }
            }else{
                if((valid != null && valid!=null && valid.getProjectChargeMode() ==2) || visitorTime == 1){
                    codeResult = this.getNewQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                            appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(),
                            Integer.valueOf(appGetVisitPassWordDTO.getTimeLimit()), elevatorTemAutList, elevatorMap, appGetVisitPassWordDTO.getCountLimit());
                }else {
                    codeResult = this.getQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                            appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(),Integer.valueOf(appGetVisitPassWordDTO.getTimeLimit()),elevatorTemAutList,elevatorMap);
                    if(codeLength != null && codeResult.get("qrcode").toString().toUpperCase().length() >= codeLength * 2){
                        codeResult = this.getNewQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                                appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(),
                                Integer.valueOf(appGetVisitPassWordDTO.getTimeLimit()), elevatorTemAutList, elevatorMap, appGetVisitPassWordDTO.getCountLimit());
                    }
                }
            }
            passPO.setFloorNum(StringHandlerUtil.getNullOrStringForObject(codeResult.get("floorNo")));
            passPO.setQrcode(codeResult.get("qrcode").toString().toUpperCase());
            passPO.setMac(StringHandlerUtil.getNullOrStringForObject(codeResult.get("mac")));
            passPO.setVisitorUuid(StringHandlerUtil.getNullOrStringForObject(codeResult.get("uid")));
            passPO.setBatch(codeResult.get("batch") != null ? Integer.valueOf(codeResult.get("batch").toString()) : 1);
        }else{
            passPO.setQrcode("00000000000000000000000000000000000000000000000000");
        }
        //生成二维码图片
        BufferedImage bim = QrcodeUtils.getQR_CODEBufferedImage(passPO.getQrcode(), BarcodeFormat.QR_CODE, 300, 300, QrcodeUtils.getDecodeHintType());
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(bim, "png", out);
        InputStream input = new ByteArrayInputStream(out.toByteArray());
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                input,
                "png",
                FILE_ACCESS_URL,
                FileCatalogEnum.VISITOR_PASS_QRCODE_FILE.getType()
        );
        Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
        Boolean returnCode = (Boolean)resultMap.get("returnCode");
        if (returnCode == true){
            passPO.setQrcodeUrl(resultMap.get("accessPath").toString());
        }
        passPO.setProjectId(appGetVisitPassWordDTO.getProjectId());
        //设置有效结束时间 增加24小时
//        if(StringUtils.isNotBlank(appGetVisitPassWordDTO.getTimeLimit()) && appGetVisitPassWordDTO.getTimeLimit().length() > 4) {
//            passPO.setEndTime(DateUtil.addCurrentTime(passPO.getStartTime(),24*60*60*1000));
//        }else {
//            if(!onDay) {
        //由于在后台配置自定义时间 若时长在25天和30天之间，DateUtil.addCurrentTime 计算结束时间会有问题，故在此做了兼容
        if(Integer.parseInt(appGetVisitPassWordDTO.getTimeLimit())>=36000){
            passPO.setEndTime(DateUtil.getAddDay(passPO.getStartTime(),Integer.valueOf(appGetVisitPassWordDTO.getTimeLimit())/60/24));
        }else{
            passPO.setEndTime(DateUtil.addCurrentTime(passPO.getStartTime(),
                    Integer.valueOf(appGetVisitPassWordDTO.getTimeLimit()) * 60 * 1000));
        }
//            }
//        }
        passPO.setNum(Integer.valueOf(appGetVisitPassWordDTO.getCountLimit()));
        passPO.setRoomId(appGetVisitPassWordDTO.getRoomId());
        passPO.setBuildIdTemporaryAuth(builds);
        passPO.setUnitIdTemporaryAuth(units);
        if(room!=null){
            passPO.setBuildId(room.getBuildId());
            passPO.setUnitId(room.getUnitId());
        }
        passPO.setOwnerAuthDeviceUnique(deviceStr.length()>0?deviceStr.substring(0,deviceStr.length()-1):"");
        //判断项目配置信息 生成动态密码 0在线版 1离线版
        Integer otpOnline = iAppVisitorPassCodeRecordDao.getOtpOnlineByProjectId(appGetVisitPassWordDTO.getProjectId());
        if(otpOnline == 0) {
            //在线版验证方式
            String random = StringHandlerUtil.autlSupply(4, RandomUtil.getRandomAround(9999, 0).toString(), "0");
            int repeat = 1;
            try {
                //获取写锁
                writeLock.lock();
                while (repeat > 0) {
                    //检查是否重复
                    repeat = iAppVisitorPassCodeRecordDao.checkRepeatPassword(random,
                            DateUtil.fomatDate(passPO.getStartTime(), DateUtil.YYYYMMDDHHMM),
                            DateUtil.fomatDate(passPO.getEndTime(), DateUtil.YYYYMMDDHHMM));
                    if (repeat > 0) {
                        random = StringHandlerUtil.autlSupply(4, RandomUtil.getRandomAround(9999, 0).toString(), "0");
                    }
                }
                if((valid != null && valid.getVisitorPassword() != null && 1 == valid.getVisitorPassword()) || (visitorPassword==1 && valid ==null)){
                    passPO.setPassword(random);
                } else {
                    passPO.setPassword("****");
                }
            } catch (Exception e) {
                throw e;
            } finally {
                writeLock.unlock();
            }
            passPO.setType(DynamicPasswordTypeEnum.ONLINE.getType());
        }else{
            //脱机版验证方式
            //获取加密后的项目秘钥 初始值异或取反projectId
            String encriptProjKey=StringHandlerUtil.bytesToHexStr(DesEncryptUtil.getQrcodeKey(DesEncryptUtil.QRCODE_INIT_KEY,appGetVisitPassWordDTO.getProjectId()));
            //动态密码规则 楼层（03）+权限组号（01）+四位密码
            if(codeResult==null){
                codeResult = new HashMap<>();
                if(room!=null){
                    codeResult.put("floorNo",Integer.valueOf(room.getRoomNum().substring(0, 2)));
                }
            }
            StringBuilder password =  new StringBuilder(StringHandlerUtil.autlSupply(2, ((Integer) Math.abs(Integer.valueOf(codeResult.get("floorNo").toString()))).toString(), "0"));
            if(room!=null){
                //获取权限组号
                String unitGroupNum = iAppVisitorPassCodeRecordDao.getGroupNumByUnitId(room.getUnitId());
                if(StringUtils.isNotBlank(unitGroupNum) && Integer.valueOf(unitGroupNum) <= 99){
                    password.append(unitGroupNum);
                }else{
                    password.append("00");
                }
            }
            StringBuilder encriptValue = new StringBuilder(password.toString());
            encriptValue.append(DateUtil.fomatDate(passPO.getEndTime(),"yyMMdd"));
            //获取时间段
            List<String> times = DateUtil.getIntervalTimeList("00:00:00","23:59:59",30);
            for(Integer i = 0 ; i<times.size() ; i++){
                if(i == times.size() -1 ){
                    encriptValue.append("48");
                    break;
                }else if(DateUtil.formatStringToDate(times.get(i),"HH:mm:ss").getTime() <=
                        DateUtil.formatStringToDate(DateUtil.fomatDate(passPO.getEndTime(),"HH:mm:ss"),"HH:mm:ss").getTime()
                        && DateUtil.formatStringToDate(times.get(i+1),"HH:mm:ss").getTime() >=
                        DateUtil.formatStringToDate(DateUtil.fomatDate(passPO.getEndTime(),"HH:mm:ss"),"HH:mm:ss").getTime() ){
                    encriptValue.append(StringHandlerUtil.autlSupply(2,((Integer)(i+1)).toString(),"0"));
                    break;
                }
            }
            //备用字节
            encriptValue.append("0000");
            String des = DesEncryptUtil.getUserKey(encriptValue.toString(),encriptProjKey);
            String hex = des.substring(des.length()-6,des.length());
            hex=((Integer)Integer.parseInt(hex,16)).toString();
            password.append(hex.substring(hex.length()-4,hex.length()));
            if ((valid != null && valid.getVisitorPassword() != null && 1 == valid.getVisitorPassword()) || (visitorPassword==1 && valid ==null)){
                passPO.setPassword(password.toString());
            }else {
                passPO.setPassword("****");
            }
            passPO.setType(DynamicPasswordTypeEnum.OFFLINE.getType());
        }
        String passNumber = RandomUtil.getRandomStringBySix(6);
        passPO.setPassNumber(passNumber);
        //判断生成访客为小程序的访客预约则做相对应处理
        if((appGetVisitPassWordDTO.getVisitorReservationMark()==1 || visitorTime == 2) && StringUtils.isNotBlank(appGetVisitPassWordDTO.getVisitTime())){
            passPO.setIntervieweePhone(appGetVisitPassWordDTO.getIntervieweePhone());
            if( visitorTime != 2){
                passPO.setIntervieweeName(iAppVisitorPassCodeRecordDao.getUserRealName("",appGetVisitPassWordDTO.getIntervieweePhone()));
            }
            if(visitorTime == 2 && appGetVisitPassWordDTO.getVisitorReservationMark()!=1){
                passPO.setCheckOperator("系统");
                passPO.setCheckStatus(1);
                passPO.setOwnerCheckStatus(1);
                passPO.setCheckTime(new Date());
                passPO.setOwnerCheckTime(new Date());
                passPO.setIntervieweeName(iAppVisitorPassCodeRecordDao.getUserRealName(appGetVisitPassWordDTO.getLoginUserId(),""));
            }
            passPO.setPlateNumber(appGetVisitPassWordDTO.getPlateNumber());
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String startStr = String.format("%s%s",appGetVisitPassWordDTO.getVisitTime()," 00:00:00");
            String endStr = String.format("%s%s",appGetVisitPassWordDTO.getVisitTime()," 23:59:59");
            passPO.setStartTime(format.parse(startStr));
            passPO.setEndTime(format.parse(endStr));
            passPO.setVisitorCause(appGetVisitPassWordDTO.getVisitorCause());
            //查询项目中对小程序访客单业主授权、物业授权两种的配置
            Map<String,Object> map = iAppVisitorPassCodeRecordDao.getProjectMiniInfo(appGetVisitPassWordDTO.getProjectId());
            String owner = map.get("owner").toString();
            String property = map.get("property").toString();
            passPO.setIsPushMessage(1);
            //在项目中配置的不需要业主审核
            if(owner.equals("0") || visitorTime == 2){
                passPO.setOwnerCheckStatus(1);
                passPO.setOwnerCheckTime(new Date());
                passPO.setIsPushMessage(0);
            }//在项目中配置的不需要物业审核
            if(property.equals("0") || visitorTime == 2){
                passPO.setCheckOperator("系统");
                passPO.setCheckStatus(1);
                passPO.setCheckTime(new Date());
            }

            //生成访客单号二维码图片
            BufferedImage bimForVisitor = QrcodeUtils.getQR_CODEBufferedImage(passNumber, BarcodeFormat.QR_CODE, 300, 300, QrcodeUtils.getDecodeHintType());
            ByteArrayOutputStream outForVisitor = new ByteArrayOutputStream();
            ImageIO.write(bimForVisitor, "png", outForVisitor);
            InputStream inputForVisitor = new ByteArrayInputStream(outForVisitor.toByteArray());
            UploadFileUtil.UploadFile uploadFileUtilInfo = new UploadFileUtil().new UploadFile(
                    FILE_FTP_HOST,
                    FILE_FTP_USERNAME,
                    FILE_FTP_PASSWORD,
                    FILE_FTP_PORT,
                    inputForVisitor,
                    "png",
                    FILE_ACCESS_URL,
                    FileCatalogEnum.VISITOR_PASS_QRCODE_FILE.getType()
            );
            Map<String, Object> resultMapInfo = UploadFileUtil.uploadFile(uploadFileUtilInfo);
            Boolean returnCodeInfo = (Boolean)resultMapInfo.get("returnCode");
            if (returnCodeInfo == true){
                passPO.setPassQrCodeUrl(resultMapInfo.get("accessPath").toString());
            }
        }else{
            passPO.setCheckOperator("系统");
            passPO.setCheckStatus(1);
            passPO.setOwnerCheckStatus(1);
            passPO.setCheckTime(new Date());
            passPO.setOwnerCheckTime(new Date());
            passPO.setIntervieweeName(iAppVisitorPassCodeRecordDao.getUserRealName(appGetVisitPassWordDTO.getLoginUserId(),""));
        }
        iAppVisitorPassCodeRecordDao.save(SqlUtil.durableData(passPO, PlatformConstants.TABLE_SAVE));

        //发送临时权限数据
        List<DeviceBusinessChangeLogPO> changes = new ArrayList<>();
        List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
        List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
        Map<String,Object> auth = new HashMap<>();
        auth.put("userId",passPO.getPassId());
        auth.put("projectId",passPO.getProjectId());
        auth.put("type",2);
        DeviceBusinessChangeLogPO po=new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_TEMP_AUTH,JsonUtil.toJSON(auth),passPO.getProjectId());
        changes.add(po);
        DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(passPO.getProjectId(),CloudElevatorChangeBusinessEnum.PUSH_TEMP_AUTH,JsonUtil.toJSON(auth));
        elevatorChanges.add(elevatorPo);
        DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(passPO.getProjectId(),CloudEntranceChangeBusinessEnum.PUSH_TEMP_AUTH, JsonUtil.toJSON(auth));
        entranceChanges.add(entrancePO);
        JSONObject dataJs = new JSONObject();
        dataJs.put("data",changes);
        //发送云对讲业务指令
        messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE, RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
        dataJs.put("data",elevatorChanges);
        //推送云电梯业务指令
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                JsonUtil.toJSON(dataJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
        //发送云门禁业务指令
        dataJs.put("data",entranceChanges);
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                JSON.toJSONString(dataJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
        );
        return passPO;
    }


    /**
     * <desc>
     *      保存访客人脸信息
     * </desc>
     *
     * @param passId 访客信息编号
     * @param uploadFilePath 图片地址
     * @param vFaceId 百度中的人脸编号
     * @param projectId 项目编号
     * @param idcardKey 身份证序号
     * @param idcardKey 访客预约标识
     * @return sql执行行数
     * @author Qiang.S
     * @createDate 2019/02/27
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer setVisitPassFace(String passId, String uploadFilePath, String vFaceId, String projectId, String idcardKey, Integer visitorReservationMark) throws Exception {
        if (visitorReservationMark == 0) {
            List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
            JSONObject json = new JSONObject();
            json.put("userId", passId);//访客推送的时候使用V- + 访客记录编号  来区分业主还是访客
            json.put("projectId", projectId);
            DeviceBusinessChangeLogPO deviceBusinessChangeLogPO =
                    new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_USER_PROJECT, json,projectId);
            changeLogPOS.add(deviceBusinessChangeLogPO);
            JSONObject dataJs = new JSONObject();
            dataJs.put("data",changeLogPOS);
            messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                    JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);

            // 云门禁
            List<DeviceBusinessEntranceChangeLogPO> changeEntranceLogPOS = new ArrayList<>();
            changeEntranceLogPOS.add(new DeviceBusinessEntranceChangeLogPO(CloudEntranceChangeBusinessEnum.PUSH_USER_PROJECT, json, projectId));
            dataJs.put("data", changeEntranceLogPOS);
            //发送云门禁指令
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                    JSON.toJSONString(dataJs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
            );
            //根据passId查询该访客记录业主和物业的审批状态
            AppGetVisitorRecordPageVO recordPageVO = iAppVisitorPassCodeRecordDao.getVisitorPassByPassId(passId);
            //有身份证序号时发送云门禁和云电梯指令
            if (!"".equals(idcardKey) || (recordPageVO.getOwnerCheckStatus()==1 && recordPageVO.getCheckStatus()==1)) {
                //云电梯
                DeviceBusinessElevatorChangeLogPO deviceBusinessElevatorChangeLogPO
                        = new DeviceBusinessElevatorChangeLogPO(projectId,
                        CloudElevatorChangeBusinessEnum.PUSH_USER_PROJECT,json.toJSONString());
                List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS = new ArrayList<>();
                deviceElevatorChangeLogPOS.add(deviceBusinessElevatorChangeLogPO);
                dataJs.put("data",deviceElevatorChangeLogPOS);
                messageSender.send(
                        RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                        JsonUtil.toJSON(dataJs),
                        RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
            }
        }
        return iAppVisitorPassCodeRecordDao.setVisitPassFace(passId, uploadFilePath, vFaceId);
    }


    /**
     * <desc>
     *      生成访客通行二维码
     * </desc>
     *
     * @param doorIds 门禁id（机号） 多个,号分隔
     * @param projectId 项目id
     * @param userId 用户id
     * @param roomInfoPO 房间实体
     * @param phoneNum 当前用户手机号
     * @return
     */
    private Map<String,Object> getNewQrCode(PropertyQrcodeValidVO valid,List<AppFloorDevicesVO> floorVos,String doorIds,String projectId,
                                         String startTime,String userId,RoomInfoPO roomInfoPO,String phoneNum,
                                         Integer timeLimit,List<String> elevatorTemAutList,Map<String,String> elevatorMap,
                                         String countLimit) throws NoSuchProviderException, ParseException {
        Map<String,Object> result = new HashMap<>();
        List<String> currentFloorUnique=new ArrayList<>();
        if(roomInfoPO!=null){
            //获取当前楼栋拥有的电梯设备唯一码
            currentFloorUnique=iAppDeviceDao.getFloorUniqueByBuildIdAndUnitId(roomInfoPO.getBuildId(), roomInfoPO.getUnitId());
            if(!elevatorTemAutList.isEmpty()){
                currentFloorUnique.addAll(elevatorTemAutList);
            }
            if(currentFloorUnique == null || currentFloorUnique.isEmpty()){
                //如果当前楼栋的电梯设备唯一码为空，获取用户在当前项目下有权限的所有的电梯设备
                StringBuilder floorIds = new StringBuilder();
                floorVos.forEach(floor->{
                    floorIds.append(floor.getDeviceId()+",");
                });
                if(floorIds.length() > 0) {
                    currentFloorUnique = iAppDeviceDao.getNotHaveAddressElevators(StringHandlerUtil.splitString(floorIds.toString()));
                }
            }
        }
        //用户有权限的且在当前楼栋的设备机号
        StringBuilder authFloors=new StringBuilder("");
        for(AppFloorDevicesVO projectFloors:floorVos){
            currentFloorUnique.forEach(buildFloorUnique->{
                if(projectFloors.getDeviceUnique().equals(buildFloorUnique)){
                    //解析设备唯一码获取设备机号
                    if(!authFloors.toString().contains(buildFloorUnique.substring(buildFloorUnique.length()-4,buildFloorUnique.length()))){
                        authFloors.append(buildFloorUnique.substring(buildFloorUnique.length()-4,buildFloorUnique.length())+",");
                    }
                }
            });
        }
        if(roomInfoPO==null){
            for(AppFloorDevicesVO projectFloors:floorVos){
                if(!authFloors.toString().contains(projectFloors.getDeviceUnique().substring(projectFloors.getDeviceUnique().length()-4,projectFloors.getDeviceUnique().length()))){
                    authFloors.append(projectFloors.getDeviceUnique().substring(projectFloors.getDeviceUnique().length()-4,projectFloors.getDeviceUnique().length())+",");
                }
            }
        }
        //开始拼接二维码
        StringBuilder heard=new StringBuilder("ITL:{L:");
        StringBuilder content = new StringBuilder();
        //协议版本 1Byte, Hex码
        content.append("V:"+AppQrcodeProtocolVersionEnum.INITIAL.getType()+",");
        //用户uid
        VisitorQrcodeVO vo = (VisitorQrcodeVO)redisService.getObject(RedisConstant.VISITOR_QRCODE_UID_REDIS_KEY + projectId, VisitorQrcodeVO.class);
        if(vo==null){
            vo = new VisitorQrcodeVO();
            vo.setUid(StringHandlerUtil.autlSupply(8,"1","0"));
            Date now = DateUtil.formatStringToDate(DateUtil.fomatDate(DateUtil.getAddDay(new Date(), 1), DateUtil.YMDSQL), DateUtil.YMDSQL);
            vo.setEndTime(now);
            redisService.set(RedisConstant.VISITOR_QRCODE_UID_REDIS_KEY+projectId,RedisConstant.VISITOR_QRCODE_UID_REDIS_CACHE_TIME,vo);
        }else{
            if(vo.getEndTime().getTime() > (new Date()).getTime()) {
                Integer count = (Integer.valueOf(vo.getUid()) + 1);
                vo.setUid(StringHandlerUtil.autlSupply(8,count.toString(),"0"));
            }else{
                vo.setUid(StringHandlerUtil.autlSupply(8,"1","0"));
                Date now = DateUtil.formatStringToDate(DateUtil.fomatDate(DateUtil.getAddDay(new Date(), 1), DateUtil.YMDSQL), DateUtil.YMDSQL);
                vo.setEndTime(now);
            }
            redisService.set(RedisConstant.VISITOR_QRCODE_UID_REDIS_KEY+projectId,RedisConstant.VISITOR_QRCODE_UID_REDIS_CACHE_TIME,vo);
        }
        content.append("U:"+vo.getUid()+",");
        //用户类型 1Byte，Hex码。 暂定0x11表示物业管理员；
        content.append("M:"+AppQrcodeUserTypeEnum.VISITOR.getType()+",");
        //房间编号
        content.append("H:00,");
        //批次号批次或流水号：“B:xxxx”其中“B”表示标识，批次值占用2个字节，用16进制表示0x0000—0xFFFF。
        content.append("I:0001,");
        //启用时间
        //生成日期 格式 yyMMddHHmm 由于设备时间与后台实际存在相差几分钟的情况，故生成二维码的有效开始时间提前十分钟
        Calendar beforeTime = Calendar.getInstance();
        beforeTime.setTime(DateUtil.formatStringToDate(startTime,DateUtil.YYYYMMDDHHMM));
        beforeTime.add(Calendar.MINUTE, -10);// 10分钟之前的时间
        Date beforeD = beforeTime.getTime();
        startTime = DateUtil.fomatDate(beforeD,DateUtil.YYMMDDHHMM);
        String validCount;
        if(valid != null && ((valid.getProjectChargeMode() == 2 && valid.getRoomChargeMode() == 1) || (valid.getVisitorQrCodeTimesRestrict()!=null && valid.getVisitorQrCodeTimesRestrict() == 1))){
            validCount = StringHandlerUtil.autlSupply(4,countLimit!=null ? Integer.toHexString(Integer.valueOf(countLimit)).toUpperCase() : "01","0").toUpperCase();
        }else{
            validCount = "00";
        }
        timeLimit+=10;
        content.append("T:" +startTime+ ",");
        //有效时间 hex 码
        content.append("P:"+StringHandlerUtil.autlSupply(4,Integer.toHexString(Integer.valueOf(timeLimit)),"0").toUpperCase()+",");
        //有效次数 hex码
        content.append("S:"+validCount+",");
        if(validCount.length()>2){
            validCount=validCount.substring(2,4);
        }
        String value =startTime+StringHandlerUtil.autlSupply(4,Integer.toHexString(Integer.valueOf(timeLimit)),"0").toUpperCase()+validCount;
        String identifier="";
        //电梯门禁标识 如有电梯和门禁权限时为0x03；只有电梯而无门禁权限时为0x01；只有门禁权限时为0x02
        if(StringUtils.isNotBlank(doorIds) && StringUtils.isNotBlank(authFloors.toString())){
            identifier="03";
        }else if(StringUtils.isNotBlank(doorIds)){
            identifier="02";
        }else if(StringUtils.isNotBlank(authFloors.toString())){
            identifier="01";
        }else{
            identifier="00";
        }
        if(!identifier.equals("00")) {
            //转换得到电梯及门禁数组
            String doors[] = StringHandlerUtil.splitString(doorIds);
            String floors[] = StringHandlerUtil.splitString(authFloors.toString());
            //门禁
            if(!identifier.equals("01")) {
                //门禁数量 HEX码
                content.append("G:{");
                if (doors.length > 0 && doors.length < 255) {
                    String n1 = StringHandlerUtil.assembleQrcodeDeviceNum(doors);
                    String n2 = StringHandlerUtil.assembleNewDeviceNum(doors);
                    if(n1.length() > n2.length()) {
                        content.append("N2:" + n2);
                    }else{
                        content.append("N1:" + n1);
                    }
                }else{
                    content.append("N3:0");
                }
                content.append("},");
            }
            //电梯
            if(!identifier.equals("02")) {
                Map<String,Set<String>> builds = new HashMap<>();
                String[] commonFloor = new String[100];
                //对电梯按照楼层权限权限分组
                for(String f : floors){
                    //电梯权限 HEX码
                    String floorNo = "";
                    StringBuffer strBuffer = new StringBuffer();
                    if(elevatorTemAutList.contains(projectId + "1" + f)){
                        String temAuthFloor = elevatorMap.get(projectId + "1" + f).toString();
                        if(temAuthFloor.contains(",")){
                            String[] arr = temAuthFloor.split(",");
                            for(String str : arr) {
                                floorNo = iAppDeviceDao.getFloorAuthByFloorNumAndDeviceUnique(str, projectId + "1" + f);
                                if(StringUtils.isNotBlank(floorNo)){
                                    strBuffer.append(floorNo+",");
                                }
                            }
                            if(StringUtils.isNotBlank(floorNo)){
                                floorNo = strBuffer.deleteCharAt(strBuffer.length()-1).toString();
                            }
                            if(StringUtils.isNotEmpty(floorNo)) {
                                boolean add = false;
                                for (String k : builds.keySet()) {
                                    if (k.equals(floorNo)) {
                                        Set<String> deviceUniques = builds.get(k);
                                        deviceUniques.add(f);
                                        add = true;
                                    }
                                }
                                if (!add) {
                                    Set<String> deviceUniques = new HashSet<>();
                                    deviceUniques.add(f);
                                    builds.put(floorNo, deviceUniques);
                                }
                            }
                            continue;
                        }else{
                            floorNo = iAppDeviceDao.getFloorAuthByFloorNumAndDeviceUnique(temAuthFloor, projectId + "1" + f);
                        }
                    }else{
                        if(roomInfoPO!=null){
                            floorNo = iAppDeviceDao.getFloorAuthByFloorNumAndDeviceUnique(Integer.valueOf(roomInfoPO.getRoomNum().substring(0, 2)).toString(), projectId + "1" + f);
                        }
                    }

                    if(StringUtils.isNotEmpty(floorNo)) {
                        // 由于共享电梯项目 需求 上下都需收费，故将共同楼层权限加至二维码中，已和产品确认处理后只开放不点亮
                        commonFloor = StringHandlerUtil.splitString(iAppDeviceDao.getCommonFloorByDeviceUnique(projectId + "1" +  StringHandlerUtil.autlSupply(4, f, "0")));
                        if(commonFloor!=null && commonFloor.length>0 && valid !=null && valid.getProjectChargeMode() == 2){
                            String commonFloorAuth = iAppDeviceDao.getCommonFloorAuthByDeviceUnique(commonFloor,projectId + "1" +  StringHandlerUtil.autlSupply(4, f, "0"));
                            LOG.info("查询数据commonFloor="+commonFloor +"deviceUnique = " + projectId + "1" +  StringHandlerUtil.autlSupply(4, f, "0"));
                            if (commonFloorAuth != null && commonFloorAuth != ""){
                                floorNo = floorNo +","+commonFloorAuth;
                            }
                        }
                        boolean add = false;
                        for (String k : builds.keySet()) {
                            if (k.equals(floorNo)) {
                                Set<String> deviceUniques = builds.get(k);
                                deviceUniques.add(f);
                                add = true;
                            }
                        }
                        if (!add) {
                            Set<String> deviceUniques = new HashSet<>();
                            deviceUniques.add(f);
                            builds.put(floorNo, deviceUniques);
                        }
                    }
                }
                for(String floor : builds.keySet()){
                    content.append("Q:{");
                    //所属单元电梯机号 HEX码
                    //设置机号权限N1：xxx
                    String n1  = StringHandlerUtil.assembleQrcodeDeviceNum(builds.get(floor).toArray(new String[builds.get(floor).size()]));
                    String n2 = StringHandlerUtil.assembleNewDeviceNum(builds.get(floor).toArray(new String[builds.get(floor).size()]));
                    if(n1.length() > n2.length()) {
                        content.append("N2:" + n2 + ",");
                    }else{
                        content.append("N1:" + n1 + ",");
                    }
                    //设置楼层号和直达楼层
                    n1 = StringHandlerUtil.assembleQrcodeDeviceNum(StringHandlerUtil.splitString(floor));
                    n2 = StringHandlerUtil.assembleNewDeviceNum(StringHandlerUtil.splitString(floor));
                    if(n1.length() > n2.length()) {
                        content.append("X2:" + n2 + ",");
                    }else{
                        content.append("X1:" + n1 + ",");
                    }
                    //直达楼层 共享电梯模式下 二维码权限中需包含公共楼层权限
                    if(commonFloor!=null && commonFloor.length>0  && valid !=null && valid.getProjectChargeMode() == 2){
                        floor = StringHandlerUtil.splitString(floor)[0];
                    }
                    if(valid !=null && valid.getProjectChargeMode() == 1){
                        floor = null;
                    }
                    content.append("Y:" + ((StringUtils.isBlank(floor) || floor.split(",").length>1) ? "00" :
                            StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(floor)).toUpperCase(), "0")) + "");
                    content.append("},");
                }
            }
        }
        if(roomInfoPO!=null){
            result.put("floorNo",Integer.valueOf(roomInfoPO.getRoomNum().substring(0, 2)));
        }
        //获取项目秘钥
        String projectKey=iAppDeviceDao.getQrcodeProjectKey(projectId);
        String mac="K:"+DesEncryptUtil.newOwnerAndVisitorMacEncrypt(value, projectKey, content.toString());
        String qrcode = heard.toString()+ StringHandlerUtil.autlSupply(4,Integer.toHexString((content + mac).length()).toUpperCase(),"0") +","+content+mac+"}";
        result.put("qrcode",qrcode);
        result.put("mac",mac.substring(2,10));
        result.put("batch",1);
        result.put("uid",vo.getUid());
        return result;
    }

    /**
     * <desc>
     *      生成访客通行二维码
     * </desc>
     *
     * @param doorIds 门禁id（机号） 多个,号分隔
     * @param projectId 项目id
     * @param userId 用户id
     * @param roomInfoPO 房间实体
     * @param phoneNum 当前用户手机号
     * @return
     */
    private Map<String,Object> getQrCode(PropertyQrcodeValidVO valid,List<AppFloorDevicesVO> floorVos,String doorIds,String projectId,
                                         String startTime,String userId,RoomInfoPO roomInfoPO,String phoneNum,Integer timeLimit,List<String> elevatorTemAutList,Map<String,String> elevatorMap) throws NoSuchProviderException, ParseException {
        Map<String,Object> result = new HashMap<>();
        //获取当前楼栋拥有的电梯设备唯一码
        List<String> currentFloorUnique= null;
        if(roomInfoPO!=null){
            currentFloorUnique=iAppDeviceDao.getFloorUniqueByBuildIdAndUnitId(roomInfoPO.getBuildId(), roomInfoPO.getUnitId());
            if(!elevatorTemAutList.isEmpty()){
                currentFloorUnique.addAll(elevatorTemAutList);
            }
        }
        if(currentFloorUnique == null || currentFloorUnique.isEmpty()){
            //如果当前楼栋的电梯设备唯一码为空，获取用户在当前项目下有权限的所有的电梯设备
            StringBuilder floorIds = new StringBuilder();
            floorVos.forEach(floor->{
                floorIds.append(floor.getDeviceId()+",");
            });
            if(floorIds.length() > 0) {
                currentFloorUnique = iAppDeviceDao.getNotHaveAddressElevators(StringHandlerUtil.splitString(floorIds.toString()));
            }
        }
        //用户有权限的且在当前楼栋的设备机号
        StringBuilder authFloors=new StringBuilder("");
        for(AppFloorDevicesVO projectFloors:floorVos){
            currentFloorUnique.forEach(buildFloorUnique->{
                if(projectFloors.getDeviceUnique().equals(buildFloorUnique)){
                    //解析设备唯一码获取设备机号
                    if(!authFloors.toString().contains(buildFloorUnique.substring(buildFloorUnique.length()-4,buildFloorUnique.length()))){
                        authFloors.append(buildFloorUnique.substring(buildFloorUnique.length()-4,buildFloorUnique.length())+",");
                    }
                }
            });
        }
        if(roomInfoPO==null){
            for(AppFloorDevicesVO projectFloors:floorVos){
                if(!authFloors.toString().contains(projectFloors.getDeviceUnique().substring(projectFloors.getDeviceUnique().length()-4,projectFloors.getDeviceUnique().length()))){
                    authFloors.append(projectFloors.getDeviceUnique().substring(projectFloors.getDeviceUnique().length()-4,projectFloors.getDeviceUnique().length())+",");
                }
            }
        }
        //开始拼接二维码
        StringBuilder qrcode=new StringBuilder("");
        StringBuilder header = new StringBuilder("");
        //协议版本 1Byte, Hex码
        header.append(AppQrcodeProtocolVersionEnum.FOURTH.getType());
        //用户类型 1Byte，Hex码。 暂定0x11表示物业管理员；0x12表示业主；0x13表示访客
        header.append(AppQrcodeUserTypeEnum.OWNER.getType());
        //用户uid
        VisitorQrcodeVO vo = (VisitorQrcodeVO)redisService.getObject(RedisConstant.VISITOR_QRCODE_UID_REDIS_KEY + projectId, VisitorQrcodeVO.class);
        if(vo==null){
            vo = new VisitorQrcodeVO();
            vo.setUid(StringHandlerUtil.autlSupply(12,"1","0"));
            Date now = DateUtil.formatStringToDate(DateUtil.fomatDate(DateUtil.getAddDay(new Date(), 1), DateUtil.YMDSQL), DateUtil.YMDSQL);
            vo.setEndTime(now);
            redisService.set(RedisConstant.VISITOR_QRCODE_UID_REDIS_KEY+projectId,RedisConstant.VISITOR_QRCODE_UID_REDIS_CACHE_TIME,vo);
        }else{
            if(vo.getEndTime().getTime() > (new Date()).getTime()) {
                Integer count = (Integer.valueOf(vo.getUid()) + 1);
                vo.setUid(StringHandlerUtil.autlSupply(12,count.toString(),"0"));
            }else{
                vo.setUid(StringHandlerUtil.autlSupply(12,"1","0"));
                Date now = DateUtil.formatStringToDate(DateUtil.fomatDate(DateUtil.getAddDay(new Date(), 1), DateUtil.YMDSQL), DateUtil.YMDSQL);
                vo.setEndTime(now);
            }
            redisService.set(RedisConstant.VISITOR_QRCODE_UID_REDIS_KEY+projectId,RedisConstant.VISITOR_QRCODE_UID_REDIS_CACHE_TIME,vo);
        }
        //生成日期 格式 yyMMddHHmm 由于设备时间与后台实际存在相差几分钟的情况，故生成二维码的有效开始时间提前十分钟
        Calendar beforeTime = Calendar.getInstance();
        beforeTime.setTime(DateUtil.formatStringToDate(startTime,DateUtil.YYYYMMDDHHMM));
        beforeTime.add(Calendar.MINUTE, -10);// 10分钟之前的时间
        Date beforeD = beforeTime.getTime();
        startTime = DateUtil.fomatDate(beforeD,DateUtil.YYMMDDHHMM);
        qrcode.append(vo.getUid());
        qrcode.append(startTime);
        //新用户类型
//        String cacheKey=RedisConstant.REDIS_APP_VISITOR_QRCODE_SERIAL_NUMBER_CACHE+userId+ DateUtil.fomatDate(new Date(), DateUtil.YYMMDD);
//        Integer serialNumber=(Integer)redisService.getObject(cacheKey, Integer.class);
//        if(serialNumber!=null){
//            qrcode.append(StringHandlerUtil.autlSupply(2,Integer.toHexString(serialNumber).toUpperCase(),"0"));
//        }else{
//            serialNumber=1;
//            qrcode.append(StringHandlerUtil.autlSupply(2,Integer.toHexString(serialNumber).toUpperCase(),"0"));
//        }
//        redisService.set(cacheKey, RedisConstant.REDIS_APP_VISITOR_QRCODE_SERIAL_NUMBER_CACHE_TIME, Integer.valueOf(serialNumber)+1);
        qrcode.append("34");
        //有效时间 hex 码
        if(timeLimit==null) {
            qrcode.append("90");
        }else{
            qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString((timeLimit+10) / 10),"0").toUpperCase());
        }
        //有效次数 hex码
        if(valid!=null && ((valid.getProjectChargeMode() == 2 && valid.getRoomChargeMode() == 1) ||
                (valid.getVisitorQrCodeTimesRestrict()!=null && valid.getVisitorQrCodeTimesRestrict() == 1))){
            qrcode.append("01");
        }else{
            qrcode.append("00");
        }
        String identifier="";
        //电梯门禁标识 如有电梯和门禁权限时为0x03；只有电梯而无门禁权限时为0x01；只有门禁权限时为0x02
        if(StringUtils.isNotBlank(doorIds) && StringUtils.isNotBlank(authFloors.toString())){
            qrcode.append("03");
            identifier="03";
        }else if(StringUtils.isNotBlank(doorIds)){
            qrcode.append("02");
            identifier="02";
        }else if(StringUtils.isNotBlank(authFloors.toString())){
            qrcode.append("01");
            identifier="01";
        }else{
            qrcode.append("00");
            identifier="00";
        }
        if(!identifier.equals("00")) {
            //转换得到电梯及门禁数组
            String doors[] = StringHandlerUtil.splitString(doorIds);
            String floors[] = StringHandlerUtil.splitString(authFloors.toString());
            //门禁
            if(!identifier.equals("01")) {
                //门禁数量 HEX码
                qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(doors.length).toUpperCase(), "0"));
                //门禁机号 HEX码
                qrcode.append(StringHandlerUtil.assembleDeviceNum(doors));
            }
            //电梯
            if(!identifier.equals("02")) {
                Map<String,Set<String>> builds = new HashMap<>();
                //对电梯按照楼层权限权限分组
                for(String f : floors){
                    //电梯权限 HEX码
                    String floorNo = "";
                    StringBuffer strBuffer = new StringBuffer();
                    if(elevatorTemAutList.contains(projectId + "1" + f)){
                        String temAuthFloor = elevatorMap.get(projectId + "1" + f).toString();
                        if(temAuthFloor.contains(",")){
                            String[] arr = temAuthFloor.split(",");
                            for(String str : arr) {
                                floorNo = iAppDeviceDao.getFloorAuthByFloorNumAndDeviceUnique(str, projectId + "1" + f);
                                if(StringUtils.isNotBlank(floorNo)){
                                    strBuffer.append(floorNo+",");
                                }
                            }
                            if(StringUtils.isNotBlank(floorNo)){
                                floorNo = strBuffer.deleteCharAt(strBuffer.length()-1).toString();
                            }
                            if(StringUtils.isNotEmpty(floorNo)) {
                                boolean add = false;
                                for (String k : builds.keySet()) {
                                    if (k.equals(floorNo)) {
                                        Set<String> deviceUniques = builds.get(k);
                                        deviceUniques.add(f);
                                        add = true;
                                    }
                                }
                                if (!add) {
                                    Set<String> deviceUniques = new HashSet<>();
                                    deviceUniques.add(f);
                                    builds.put(floorNo, deviceUniques);
                                }
                            }
                            continue;
                        }else{
                            floorNo = iAppDeviceDao.getFloorAuthByFloorNumAndDeviceUnique(temAuthFloor, projectId + "1" + f);
                        }
                    }else{
                        if(roomInfoPO!=null){
                            floorNo = iAppDeviceDao.getFloorAuthByFloorNumAndDeviceUnique(Integer.valueOf(roomInfoPO.getRoomNum().substring(0, 2)).toString(), projectId + "1" + f);
                        }
                    }

                    if(StringUtils.isNotEmpty(floorNo)) {
                        boolean add = false;
                        for (String k : builds.keySet()) {
                            if (k.equals(floorNo)) {
                                Set<String> deviceUniques = builds.get(k);
                                deviceUniques.add(f);
                                add = true;
                            }
                        }
                        if (!add) {
                            Set<String> deviceUniques = new HashSet<>();
                            deviceUniques.add(f);
                            builds.put(floorNo, deviceUniques);
                        }
                    }
                }
                //有权限的电梯楼栋单元数量 最多8个单元 超过8个单元按拥有所有电梯权限处理
                qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(builds.keySet().size()).toUpperCase(), "0"));
                for(String floor : builds.keySet()){
                    //所属单元电梯数量 HEX 码
                    qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(builds.get(floor).size()).toUpperCase(), "0"));
                    //所属单元电梯机号 HEX码
                    qrcode.append(StringHandlerUtil.assembleDeviceNum(builds.get(floor).toArray(new String[builds.get(floor).size()])));
                    //设置有权限的楼层数量
                    qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(floor.split(",").length).toUpperCase(), "0"));
                    //设置楼层号和直达楼层
                    qrcode.append(StringHandlerUtil.assembleDeviceNum(floor.split(",")));
                    qrcode.append((StringUtils.isBlank(floor) || floor.split(",").length>1) ? "00" : StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(floor)).toUpperCase(), "0"));
                }
            }
        }
        if(roomInfoPO!=null){
            result.put("floorNo",Integer.valueOf(roomInfoPO.getRoomNum().substring(0, 2)));
        }
        String value=qrcode.substring(12,28);
        //获取项目秘钥
        String projectKey=iAppDeviceDao.getQrcodeProjectKey(projectId);
        qrcode = new StringBuilder(header.toString()+qrcode.toString());
        qrcode=qrcode.append(DesEncryptUtil.ownerAndVisitorMacEncrypt(value, projectKey, qrcode.toString()));
        result.put("qrcode",qrcode);
        result.put("uid",vo.getUid().substring(vo.getUid().length()-8,vo.getUid().length()));
        result.put("mac",qrcode.substring(qrcode.length()-8,qrcode.length()));
        result.put("batch",1);
        return result;
    }

    /**
     * <desc>
     *      获取分页数据
     * </desc>
     *
     * @param pageDTO   参数DTO
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/31
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<AppGetVisitorRecordPageVO> getPage(AppGetVisitorRecordPageDTO pageDTO) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(pageDTO);
        //分页类默认pageSize为20
        Page<AppGetVisitorRecordPageVO> page = new Page<>();
        page.getPage().setPageSize(pageDTO.getPageSize());
        page.getPage().setCurrentPage(pageDTO.getPageNo());
        params.put("currentPage", page.getPage().getStartSlip());
        params.put("pageSize", page.getPage().getPageSize());
        //填充返回数据集
        page.setRows(iAppVisitorPassCodeRecordDao.getPage(params), iAppVisitorPassCodeRecordDao.getPageCount(params));
        for(AppGetVisitorRecordPageVO vo:page.getRows()){
            //设置密码状态 0正常 1过期
            if(DateUtil.formatStringToDate(vo.getEndTime(),DateUtil.YYYYMMDDHHMM).compareTo(new Date())>0){
                vo.setPassStatus("0");
            }else{
                vo.setPassStatus("1");
            }
        }
//        Collections.sort(page.getRows());
        List<AppGetVisitorRecordPageVO> list = page.getRows();
//        if(page.getPage().getStartSlip()<=200) {
//            for (int i = page.getPage().getStartSlip() >= 200 ? 200 - page.getPage().getPageSize() : page.getPage().getStartSlip();
//                 i < (page.getPage().getStartSlip() + page.getPage().getPageSize() > 200 ? 200 : page.getPage().getStartSlip() + page.getPage().getPageSize()); i++) {
//                if (i < page.getRows().size()) {
//                    list.add(page.getRows().get(i));
//                } else {
//                    break;
//                }
//            }
//        }
        for (AppGetVisitorRecordPageVO vo : list){
            if (StringUtils.isNotBlank(vo.getQrcode()) && StringUtils.isBlank(vo.getQrCodeUrl())) {
                //生成二维码图片
                BufferedImage bim = QrcodeUtils.getQR_CODEBufferedImage(vo.getQrcode(), BarcodeFormat.QR_CODE, 300, 300, QrcodeUtils.getDecodeHintType());
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                ImageIO.write(bim, "png", out);
                InputStream input = new ByteArrayInputStream(out.toByteArray());
                UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                        FILE_FTP_HOST,
                        FILE_FTP_USERNAME,
                        FILE_FTP_PASSWORD,
                        FILE_FTP_PORT,
                        input,
                        "png",
                        FILE_ACCESS_URL,
                        FileCatalogEnum.VISITOR_PASS_QRCODE_FILE.getType()
                );
                Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
                Boolean returnCode = (Boolean)resultMap.get("returnCode");
                if (returnCode){
                    vo.setQrCodeUrl(resultMap.get("accessPath").toString());
                }
            }
        }
        page.setRows(list);
        return page;
    }

    /**
     * <desc>
     *      获取有效的访客通行密码记录
     * </desc>
     *
     * @param projectId 项目编号
     * @param pageNo    页数
     * @param pageSize  每页数
     * @param userId    用户id
     * @return 有效的访客通行密码记录
     * @author wangzhi
     * @createDate 2019/07/11
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Map<String, Object> getAvailableVisitorPwd(String projectId, String pageNo, String pageSize, String userId) throws Exception {
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> data = new HashMap<>();
        params.put("projectId", projectId);
        params.put("userId", userId);
        // 分页索引
        if (Integer.parseInt(pageNo) > 0) {
            params.put("startSlip", (Integer.parseInt(pageNo) - 1) * Integer.parseInt(pageSize));
        } else {
            params.put("startSlip", 0);
        }
        // 分页记录数
        params.put("pageSize", Integer.parseInt(pageSize));
        List<Map<String, Object>> visitorPwdMap = iAppVisitorPassCodeRecordDao.getAvailableVisitorPwd(params);
        String passId;
        for (Map<String, Object> map : visitorPwdMap){
            passId = map.get("passId").toString();
            map.put("url",H5_VISITOR_HTML+"?passId="+URLEncoder.encode(DesEncryptUtil.aesEncryptSDK(passId, propertyOperateMiniContentAesEncryptKey)));
            if (map.get("qrcode") != null && map.get("qrCodeUrl") == null) {
                //生成二维码图片
                BufferedImage bim = QrcodeUtils.getQR_CODEBufferedImage(map.get("qrcode").toString(), BarcodeFormat.QR_CODE, 300, 300, QrcodeUtils.getDecodeHintType());
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                ImageIO.write(bim, "png", out);
                InputStream input = new ByteArrayInputStream(out.toByteArray());
                UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                        FILE_FTP_HOST,
                        FILE_FTP_USERNAME,
                        FILE_FTP_PASSWORD,
                        FILE_FTP_PORT,
                        input,
                        "png",
                        FILE_ACCESS_URL,
                        FileCatalogEnum.VISITOR_PASS_QRCODE_FILE.getType()
                );
                Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
                Boolean returnCode = (Boolean)resultMap.get("returnCode");
                if (returnCode) {
                    map.put("qrCodeUrl", resultMap.get("accessPath").toString());
                }
            }
        }
        data.put("pageCount", visitorPwdMap.size());
        data.put("data", visitorPwdMap);
        return data;
    }

    public static void main(String[] args) throws Exception {
        String str = "ITL:{L:0062,V:10,U:00000013,M:33,H:1,I:0002,T:2009161645,P:0082,S:00B8,G:{N1:1},Q:{N1:B,X2:C0,Y:02},K:7B495B1E}";
        int ssss = str.indexOf(",T:");
        String dd = str.substring(ssss+13,str.length()-1);
        System.out.println(dd);
        System.out.println(str.substring(0,ssss));
    }

    /**
     * <desc>
     *      设置已分享
     * </desc>
     *
     * @param passId   访客唯一编号
     * @return
     * @author Qiang.S
     * @createDate 2019/04/16
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void setShare(String passId) throws Exception {
        iAppVisitorPassCodeRecordDao.setShare(passId);
    }

    /**
     * <desc>
     *      根据楼栋,单元,房间查询地址
     * </desc>
     *
     * @param buildId   楼栋编号
     * @param unitId   单元编号
     * @param roomId   房间编号
     * @return
     * @author Qiang.S
     * @createDate 2019/04/16
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public String getAddress(String buildId, String unitId, String roomId) throws Exception {
        return iAppVisitorPassCodeRecordDao.getAddress(buildId,unitId,roomId);
    }

    /**
     * <desc>
     *      根据访客编号获取信息
     * </desc>
     *
     * @param passId 访客编号
     * @return 格式化响应结果
     * @author Qiang.S
     * @createDate 2019/04/24
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public AppGetVisitorRecordPageVO getVisitorPassByPassId(String passId) throws Exception {
        AppGetVisitorRecordPageVO visitorRecordPageVO = iAppVisitorPassCodeRecordDao.getVisitorPassByPassId(passId);
        if(StringUtils.isBlank(visitorRecordPageVO.getAddress())){
            visitorRecordPageVO.setAddress(visitorRecordPageVO.getCommunityName());
        }
        return visitorRecordPageVO;
    }

    /**
     * <desc>
     *      删除访客信息
     * </desc>
     *
     * @param passId 访客编号
     * @return 格式化响应结果
     * @author Qiang.S
     * @createDate 2019/04/28
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer deleteVisitorInfo(String passId) throws Exception {
        return iAppVisitorPassCodeRecordDao.deleteVisitorInfo(passId);
    }

    /**
     * <desc>
     *      获取访客预约凭证分页数据
     * </desc>
     *
     * @param pageDTO   参数DTO
     * @return
     * @author Juguang.S
     * @createDate 2019/04/29
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<MiniGetReservationProofPageVO> getReservationProofPage(MiniGetReservationProofPageDTO pageDTO) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(pageDTO);
        //分页类默认pageSize为20
        Page<MiniGetReservationProofPageVO> page = new Page<>();
        page.getPage().setPageSize(pageDTO.getPageSize());
        page.getPage().setCurrentPage(pageDTO.getCurrentPage());
        params.put("currentPage", page.getPage().getStartSlip());
        params.put("pageSize", page.getPage().getPageSize());
        String phoneNum = iAppVisitorPassCodeRecordDao.getPhoneNumByUserId(pageDTO.getLoginUserId());
        params.put("phoneNum", phoneNum);
        //填充返回数据集
        List<MiniGetReservationProofPageVO> list = iAppVisitorPassCodeRecordDao.getReservationProofPage(params);
        Integer count = iAppVisitorPassCodeRecordDao.getReservationProofPageCount(params);
        page.setRows(list,count);
        return page;
    }

    /**
     * <desc>
     *      获取访客身份通行记录
     * </desc>
     *
     * @param pageDTO   参数DTO
     * @return
     * @author Juguang.S
     * @createDate 2019/04/30
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<MiniGetVisitorPassRecordPageVO> getVisitorPassRecordPage(MiniGetReservationProofPageDTO pageDTO) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(pageDTO);
        //分页类默认pageSize为20
        Page<MiniGetVisitorPassRecordPageVO> page = new Page<>();
        page.getPage().setPageSize(pageDTO.getPageSize());
        page.getPage().setCurrentPage(pageDTO.getCurrentPage());
        params.put("currentPage", page.getPage().getStartSlip());
        params.put("pageSize", page.getPage().getPageSize());
        //填充返回数据集
        List<MiniGetVisitorPassRecordPageVO> list = iAppVisitorPassCodeRecordDao.getVisitorPassRecordPage(params);
        Integer count = iAppVisitorPassCodeRecordDao.getVisitorPassRecordPageCount(params);
        page.setRows(list, count);
        return page;
    }

     /**
     * <desc>
     *      获取访客单信息
     * </desc>
     *
     * @param userId   用户编号
     * @param projectId   项目编号
     * @return
     * @author Qiang.S
     * @createDate 2019/05/05
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<MiniGetReservationProofPageVO> getReservationVisitorInfo(String userId, String projectId) throws Exception {
        return iAppVisitorPassCodeRecordDao.getReservationVisitorInfo(userId,projectId);
    }

    /**
     * <desc>
     *      获取当前用户注册人脸信息
     * </desc>
     *
     * @param userId   用户编号
     * @param projectId   项目编号
     * @param type   当前用户身份类型 1代表业主 2代表访客
     * @return 人脸url
     * @author Juguang.S
     * @createDate 2019/05/06
     */
    @Override
    public Map<String,String> getUserFaceUrlInfo(String userId, String projectId, String type) {
        if(type.equals("1")){
            Map<String,String> map = iAppVisitorPassCodeRecordDao.getOwnerUserFaceUrlInfo(userId,projectId);
//            if(map==null || map.isEmpty()){
//                map = iAppVisitorPassCodeRecordDao.getVisitorUserFaceUrlInfo(userId,projectId);
//            }
            return map;
        }else{
            return iAppVisitorPassCodeRecordDao.getVisitorUserFaceUrlInfo(userId,projectId);
        }
    }

    /**
     * <desc>
     *      校验该访客记录是否已被物业审批并且已认证过
     * </desc>
     *
     * @param passId   访客单号
     * @return
     * @author Juguang.S
     * @createDate 2019/05/27
     */
    @Override
    public Integer isAllowedAuthenticate(String passId) {
        return iAppVisitorPassCodeRecordDao.isAllowedAuthenticate(passId);
    }

    /**
     * <desc>
     *      物业业主审核通过有效时间变更后重新处理生成二维码相关逻辑
     * </desc>
     *
     * @param appGetVisitPassWordDTO 访客密码通行记录实体类
     * @return
     * @author Juguang.S
     * @createDate 2020/09/16
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public AppVisitorPassCodeRecordPO updateQrcodeByTimeModify(AppGetVisitPassWordDTO appGetVisitPassWordDTO) throws Exception {
        String[] roomIds = StringHandlerUtil.splitString(appGetVisitPassWordDTO.getRoomId());
        appGetVisitPassWordDTO.setRoomId(roomIds[0]);
        AppVisitorPassCodeRecordPO passPO=new AppVisitorPassCodeRecordPO();
        passPO.setPassId(appGetVisitPassWordDTO.getPassId());
        passPO.setResult("SUCCESS");
        PropertyQrcodeValidVO valid=iAppDeviceDao.getPropertyQrocdeVliadInfo(roomIds[0]);
        if(valid!=null && valid.getProjectChargeMode()==2){
            Integer count = valid.getUsableCount() != null ? valid.getUsableCount() : 0;
            if(valid.getRoomChargeMode() == 1){
                if(count<=0) {
                    passPO.setResult(count.toString());
                    return passPO;
                }else if(StringUtils.isNotBlank(appGetVisitPassWordDTO.getCountLimit()) && Integer.valueOf(appGetVisitPassWordDTO.getCountLimit()) > valid.getUsableCount()){
                    passPO.setResult(count.toString());
                    return passPO;
                }
            }else if(valid.getRoomChargeMode() == 2){
                //按有效期
                Date now = DateUtil.formatStringToDate(DateUtil.fomatDate(new Date(), DateUtil.YMDSQL), DateUtil.YMDSQL);
                Date roomDate = DateUtil.formatStringToDate(valid.getEndTime(),DateUtil.YMDSQL);
                if(roomDate.getTime() < now.getTime()){
                    passPO.setResult("TIME");
                    return passPO;
                }
            }
        }
        //如果次数为空或者大于10 默认为10
        if(StringUtils.isBlank(appGetVisitPassWordDTO.getCountLimit())){
            appGetVisitPassWordDTO.setCountLimit("1000");
        }
        //查询本项目访客二维码次数限制是否开启，若开启后则将可用次数填充至次数限制字段
        Map<String,Object> qrcodeConfigure = iPropertyEquipDao.getVisitorConfigure(appGetVisitPassWordDTO.getProjectId());
        String visitorQrCodeTimesRestrict = StringHandlerUtil.getNullOrStringForObject(qrcodeConfigure.get("visitorQrCodeTimesRestrict"));
        String visitorQrCodeUsableTimes = StringHandlerUtil.getNullOrStringForObject(qrcodeConfigure.get("visitorQrCodeUsableTimes"));
        if("1".equals(visitorQrCodeTimesRestrict)){
            appGetVisitPassWordDTO.setCountLimit(visitorQrCodeUsableTimes);
        }
        passPO.setUpdateTime(new Date());
        //如果有效时间为空，默认为当前创建时间
        boolean onDay = false;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startStr = String.format("%s%s",appGetVisitPassWordDTO.getVisitTime()," 00:00:00");
        String endStr = String.format("%s%s",appGetVisitPassWordDTO.getVisitTime()," 23:59:59");
        passPO.setStartTime(format.parse(startStr));
        passPO.setEndTime(format.parse(endStr));
        if(StringUtils.isEmpty(appGetVisitPassWordDTO.getTimeLimit())){
            appGetVisitPassWordDTO.setTimeLimit("1440");
        }
        //获取房间号的楼栋信息
        RoomInfoPO room=iAppVisitorPassCodeRecordDao.getRoomBuildAndUnitInfo(appGetVisitPassWordDTO.getRoomId(), appGetVisitPassWordDTO.getProjectId(),null);
        //如果添加访客来源是小程序访客预约（包含业主和访客身份的预约）则获取受访人的userId,并后续获取受访人的设备权限等
        String intervieweeUserId = iAppVisitorPassCodeRecordDao.getUserIdbyPhoneNum(appGetVisitPassWordDTO.getIntervieweePhone());
        appGetVisitPassWordDTO.setLoginUserId(intervieweeUserId);
        StringBuffer deviceStr = new StringBuffer();
        //获取该用户在项目上所有有权限的云对讲设备
        List<Map<String,Object>> cloudAuth = iAppDeviceDao.getCloudIntercomsAuth(appGetVisitPassWordDTO.getLoginUserId(), appGetVisitPassWordDTO.getProjectId());
        AppEntranceOrCloudIntercomAuthVO cloudVO=StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.CLOUD_INTERCOM.getType(),cloudAuth);
        if(cloudVO!=null){
            for(String str : cloudVO.getDeviceIds()){
                String deviceUnique = String.format("%s%s%s",appGetVisitPassWordDTO.getProjectId(),3,str);
                deviceStr.append(String.format("%s%s",deviceUnique,","));
            }
        }
        //获取该用户在项目上所有有权限的门禁设备
        //获取用户有权限的门禁设备机号
        List<Map<String,Object>> doorAuth = iAppDeviceDao.getDoorAuth(appGetVisitPassWordDTO.getLoginUserId(), appGetVisitPassWordDTO.getProjectId());
        AppEntranceOrCloudIntercomAuthVO doorVO=StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.ENTRANCE.getType(),doorAuth);
        if(doorVO!=null){
            for(String str : doorVO.getDeviceIds()){
                String deviceUnique = String.format("%s%s%s",appGetVisitPassWordDTO.getProjectId(),2,str);
                deviceStr.append(String.format("%s%s",deviceUnique,","));
            }
        }
        //获取当前项目有权限的电梯实体类
        List<AppFloorDevicesVO> floorVos = iAppDeviceService.getFloorDevices(appGetVisitPassWordDTO.getLoginUserId(),appGetVisitPassWordDTO.getProjectId(),1);
        //处理访客的临时设备权限
        StringBuffer temporaryAuthDoor = new StringBuffer();
        StringBuffer temporaryAuthCloudTalk = new StringBuffer();
        List<AppFloorDevicesVO> elevatorTemporaryAuthList = new ArrayList<>();
        List<String> elevatorTemAutList = new ArrayList<>();
        Map<String,String> elevatorMap = new HashMap<>();
        String builds = "";
        String units = "";
        if(room!=null){
            builds = room.getBuildId();
            units = room.getUnitId();
        }
        if(StringUtils.isNotEmpty(appGetVisitPassWordDTO.getDeviceUniques())){
            Map<String,String> mainDoorElevator = new HashMap<>();
            Map<String,String> backDoorElevator = new HashMap<>();
            List<AppFloorDevicesVO> lists = iAppDeviceService.getUserTemporaryAuthFloorDevices(appGetVisitPassWordDTO.getLoginUserId(),appGetVisitPassWordDTO.getProjectId());
            String[] deviceUniqueArr = appGetVisitPassWordDTO.getDeviceUniques().split(",");
            for(String deviceUnique : deviceUniqueArr){
                Integer deviceType = Integer.parseInt(StringHandlerUtil.copySubStr(deviceUnique, 8, 1));
                switch (PropertyEquipTypeEnum.getByEquipType(deviceType)) {
                    case ENTRANCE:
                        temporaryAuthDoor.append(deviceUnique.substring(9,13)+",");
                        deviceStr.append(String.format("%s%s",deviceUnique,","));
                        break;
                    case CLOUD_INTERCOM:
                        temporaryAuthCloudTalk.append(deviceUnique.substring(9,13)+",");
                        deviceStr.append(String.format("%s%s",deviceUnique,","));
                        break;
                    case ELEVATOR:
                        String floorAuth = Integer.valueOf(room.getRoomNum().substring(0,2)).toString();
                        for(AppFloorDevicesVO devicesVO : lists){
                            if(deviceUnique.equals(devicesVO.getDeviceUnique())){
                                elevatorTemAutList.add(deviceUnique);
                                elevatorTemporaryAuthList.add(devicesVO);
                                if(devicesVO.getLiftDoorType()==1){
                                    mainDoorElevator.put(deviceUnique.substring(9,13),devicesVO.getLiveFloor());
                                }else{
                                    backDoorElevator.put(deviceUnique.substring(9,13),devicesVO.getLiveFloor());
                                }
                                if(java.util.Arrays.asList(devicesVO.getLiveFloor().split(",")).contains(floorAuth)){
                                    elevatorMap.put(deviceUnique,devicesVO.getLiveFloor());
                                }else{
                                    //所拜访房间业主的该电梯设备没有所拜访房间的楼层权限则不拼接楼层权限
                                    int count = 0;
                                    for(AppFloorDevicesVO floorDevicesVO : floorVos){
                                        Map<String,Object> addressMap = iCloudElevatorDao.getBuildAndUnitByDeviceUnique(deviceUnique);
                                        if(floorDevicesVO.getDeviceUnique().equals(deviceUnique) &&
                                                java.util.Arrays.asList(floorDevicesVO.getLiveFloor().split(",")).contains(floorAuth) &&
                                                (addressMap!=null && !addressMap.isEmpty() && addressMap.get("unitIds").toString().contains(room.getUnitId()))){
                                            elevatorMap.put(deviceUnique,devicesVO.getLiveFloor().isEmpty()?floorAuth:devicesVO.getLiveFloor() +","+floorAuth);
                                            count++;
                                            break;
                                        }
                                    }
                                    if(count==0){
                                        elevatorMap.put(deviceUnique,devicesVO.getLiveFloor());
                                    }else{
                                        elevatorMap.put(deviceUnique,devicesVO.getLiveFloor().isEmpty()?floorAuth:devicesVO.getLiveFloor() +","+floorAuth);
                                    }
                                }
                                Map<String,Object> buildAndUnit = iCloudElevatorDao.getBuildAndUnitBySn(String.format("%s%s%s",deviceUnique.substring(0,8),"0000",deviceUnique.substring(9,deviceUnique.length())));
                                if(buildAndUnit!=null && !buildAndUnit.isEmpty()){
                                    builds = String.format("%s%s%s",builds,",",buildAndUnit.get("buildId").toString());
                                    units = String.format("%s%s%s",units,",",buildAndUnit.get("unitIds").toString());
                                }
                                break;
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
            if(!mainDoorElevator.isEmpty()){
                passPO.setMainDoorElevatorAuth(JSONArray.toJSONString(mainDoorElevator));
            }
            if(!backDoorElevator.isEmpty()){
                passPO.setBackDoorElevatorAuth(JSONArray.toJSONString(backDoorElevator));
            }
        }
        String binaryCloudAuth=null;
        String binaryEntranceAuth=null;
        if(cloudVO!=null) {
            binaryCloudAuth = StringUtils.join(cloudVO.getDeviceIds().toArray(new String[cloudVO.getDeviceIds().size()]),",");
        }
        if(doorVO!=null){
            binaryEntranceAuth = StringUtils.join(doorVO.getDeviceIds().toArray(new String[doorVO.getDeviceIds().size()]),",");
        }

        //在此处根据拜访房间的正背门来筛选相对应正背门电梯的权限
        String roomDoorType = iAppVisitorPassCodeRecordDao.getRoomForDoorInfo(appGetVisitPassWordDTO.getRoomId());
        if(floorVos!=null){
            for(int i=floorVos.size()-1; i >= 0; i--){
                String liftDoorType = iAppVisitorPassCodeRecordDao.getElevatorDoorInfo(StringHandlerUtil.autlSupply(4,floorVos.get(i).getDeviceId(),"0"),appGetVisitPassWordDTO.getProjectId());
                //如果电梯是正门
                if(StringUtils.isNotBlank(roomDoorType) && StringUtils.isNotBlank(liftDoorType) && !roomDoorType.equals(liftDoorType)){
                    floorVos.remove(i);
                }
            }
        }
        //
        floorVos.addAll(elevatorTemporaryAuthList);

        //如果没有设备权限直接返回null
        Map<String,Object> codeResult = null;
        if(StringUtils.isNotBlank(binaryCloudAuth) || StringUtils.isNotBlank(binaryEntranceAuth) || (floorVos!=null && !floorVos.isEmpty())) {
            String[] cloudIds = StringHandlerUtil.splitString(binaryCloudAuth);   //云对讲机号
            String[] doorIds = StringHandlerUtil.splitString(binaryEntranceAuth);     //门禁机号
            StringBuilder dIds = new StringBuilder();
            //如果解析的云对讲设备机号不为空
            if (StringUtils.isNotBlank(binaryCloudAuth)) {
                //获取用户对应楼栋有权限的云对讲设备的机号
                dIds.append(iAppDeviceDao.getCloudDeviceIdsForBridge(appGetVisitPassWordDTO.getProjectId(),
                        room.getBuildId(), room.getUnitId(), cloudIds) + ",");
                if(StringUtils.isNotEmpty(temporaryAuthCloudTalk.toString())){
                    dIds.append(temporaryAuthCloudTalk.toString());
                }
            }
            StringBuilder entrances = new StringBuilder();
            //如果解析的门禁设备机号不为空
            if (StringUtils.isNotBlank(binaryEntranceAuth)) {
                //获取用户对应楼栋有权限的门禁设备的机号
                String notAddressDoor = iAppDeviceDao.getEntranceDeviceIdsForBridge(appGetVisitPassWordDTO.getProjectId(),
                        room.getBuildId(), room.getUnitId(), doorIds);
                entrances.append(StringUtils.isNotBlank(notAddressDoor) ? notAddressDoor : "");
                //如果有权限的门禁设备机号为空获取当前用户项目下没有设备地址的门禁设备（一卡通授权过来的设备）
                if(entrances.length() == 0){
                    entrances.append(iAppDeviceDao.getNotHaveAddressEntranceIds(doorIds,appGetVisitPassWordDTO.getProjectId()));
                }
                if(entrances.length() != 0 ){
                    if(StringUtils.isNotEmpty(temporaryAuthDoor.toString())){
                        dIds.append(temporaryAuthDoor.toString());
                    }
                    dIds.append(String.format("%s",entrances.toString()));
                }
            }
            //为了防止门禁与云对讲机号重复，现对设备机号进行去重处理
            String[] allDeviceIds = StringHandlerUtil.splitString(dIds.toString());
            Set<String> setDeviceIds = new HashSet<>();
            String deviceIds = "";
            for (String deviceId : allDeviceIds) {
                if (!deviceId.equals("null") && setDeviceIds.add(deviceId)) {
                    deviceIds += deviceId + ",";
                }
            }
            //设置门禁的id
            passPO.setDeviceId(StringUtils.isNotBlank(deviceIds) ? deviceIds.substring(0, deviceIds.length() - 1) : "");
            //获取项目二维码长度
            Integer codeLength = iAppDeviceDao.getCodeLength(appGetVisitPassWordDTO.getProjectId());
            //生成二维码信息
            if(appGetVisitPassWordDTO.getTimeLimit().length() > 4){
                if(valid != null && valid!=null && valid.getProjectChargeMode() == 2){
                    //新二维码格式
                    codeResult = this.getNewQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                            appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(),null,elevatorTemAutList,elevatorMap,
                            appGetVisitPassWordDTO.getCountLimit());
                }else {
                    codeResult = this.getQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                            appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(), null, elevatorTemAutList, elevatorMap);
                    if(codeLength != null && codeResult.get("qrcode").toString().toUpperCase().length() >= codeLength * 2){
                        codeResult = this.getNewQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                                appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(), null, elevatorTemAutList, elevatorMap,
                                appGetVisitPassWordDTO.getCountLimit());
                    }
                }
            }else{
                if(valid != null && valid!=null && valid.getProjectChargeMode() ==2){
                    codeResult = this.getNewQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                            appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(),
                            Integer.valueOf(appGetVisitPassWordDTO.getTimeLimit()), elevatorTemAutList, elevatorMap, appGetVisitPassWordDTO.getCountLimit());
                }else {
                    codeResult = this.getQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                            appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(),Integer.valueOf(appGetVisitPassWordDTO.getTimeLimit()),elevatorTemAutList,elevatorMap);
                    if(codeLength != null && codeResult.get("qrcode").toString().toUpperCase().length() >= codeLength * 2){
                        codeResult = this.getNewQrCode(valid,floorVos, deviceIds, appGetVisitPassWordDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                                appGetVisitPassWordDTO.getLoginUserId(), room, appGetVisitPassWordDTO.getLoginUserPhone(),
                                Integer.valueOf(appGetVisitPassWordDTO.getTimeLimit()), elevatorTemAutList, elevatorMap, appGetVisitPassWordDTO.getCountLimit());
                    }
                }
            }
            passPO.setQrcode(codeResult.get("qrcode").toString().toUpperCase());
        }else{
            passPO.setQrcode("00000000000000000000000000000000000000000000000000");
        }
        //生成二维码图片
        BufferedImage bim = QrcodeUtils.getQR_CODEBufferedImage(passPO.getQrcode(), BarcodeFormat.QR_CODE, 300, 300, QrcodeUtils.getDecodeHintType());
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(bim, "png", out);
        InputStream input = new ByteArrayInputStream(out.toByteArray());
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                input,
                "png",
                FILE_ACCESS_URL,
                FileCatalogEnum.VISITOR_PASS_QRCODE_FILE.getType()
        );
        Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
        Boolean returnCode = (Boolean)resultMap.get("returnCode");
        if (returnCode == true){
            passPO.setQrcodeUrl(resultMap.get("accessPath").toString());
        }
        passPO.setBuildIdTemporaryAuth(builds);
        passPO.setUnitIdTemporaryAuth(units);
        passPO.setOwnerAuthDeviceUnique(deviceStr.length()>0?deviceStr.substring(0,deviceStr.length()-1):"");
        //判断项目配置信息 生成动态密码 0在线版 1离线版
        Integer otpOnline = iAppVisitorPassCodeRecordDao.getOtpOnlineByProjectId(appGetVisitPassWordDTO.getProjectId());
        if(otpOnline == 0) {
            //在线版验证方式
            String random = StringHandlerUtil.autlSupply(4, RandomUtil.getRandomAround(9999, 0).toString(), "0");
            int repeat = 1;
            try {
                //获取写锁
                writeLock.lock();
                while (repeat > 0) {
                    //检查是否重复
                    repeat = iAppVisitorPassCodeRecordDao.checkRepeatPassword(random,
                            DateUtil.fomatDate(passPO.getStartTime(), DateUtil.YYYYMMDDHHMM),
                            DateUtil.fomatDate(passPO.getEndTime(), DateUtil.YYYYMMDDHHMM));
                    if (repeat > 0) {
                        random = StringHandlerUtil.autlSupply(4, RandomUtil.getRandomAround(9999, 0).toString(), "0");
                    }
                }
                if(valid != null && valid.getVisitorPassword() == null && 1 == valid.getVisitorPassword()){
                    passPO.setPassword(random);
                }else {
                    passPO.setPassword("*******");
                }
            } catch (Exception e) {
                throw e;
            } finally {
                writeLock.unlock();
            }
            passPO.setType(DynamicPasswordTypeEnum.ONLINE.getType());
        }else{
            //脱机版验证方式
            //获取加密后的项目秘钥 初始值异或取反projectId
            String encriptProjKey=StringHandlerUtil.bytesToHexStr(DesEncryptUtil.getQrcodeKey(DesEncryptUtil.QRCODE_INIT_KEY,appGetVisitPassWordDTO.getProjectId()));
            //动态密码规则 楼层（03）+权限组号（01）+四位密码
            if(codeResult==null){
                codeResult = new HashMap<>();
                codeResult.put("floorNo",Integer.valueOf(room.getRoomNum().substring(0, 2)));
            }
            StringBuilder password =  new StringBuilder(StringHandlerUtil.autlSupply(2, ((Integer) Math.abs(Integer.valueOf(codeResult.get("floorNo").toString()))).toString(), "0"));
            //获取权限组号
            String unitGroupNum = iAppVisitorPassCodeRecordDao.getGroupNumByUnitId(room.getUnitId());
            if(StringUtils.isNotBlank(unitGroupNum) && Integer.valueOf(unitGroupNum) <= 99){
                password.append(unitGroupNum);
            }else{
                password.append("00");
            }
            StringBuilder encriptValue = new StringBuilder(password.toString());
            encriptValue.append(DateUtil.fomatDate(passPO.getEndTime(),"yyMMdd"));
            //获取时间段
            List<String> times = DateUtil.getIntervalTimeList("00:00:00","23:59:59",30);
            for(Integer i = 0 ; i<times.size() ; i++){
                if(i == times.size() -1 ){
                    encriptValue.append("48");
                    break;
                }else if(DateUtil.formatStringToDate(times.get(i),"HH:mm:ss").getTime() <=
                        DateUtil.formatStringToDate(DateUtil.fomatDate(passPO.getEndTime(),"HH:mm:ss"),"HH:mm:ss").getTime()
                        && DateUtil.formatStringToDate(times.get(i+1),"HH:mm:ss").getTime() >=
                        DateUtil.formatStringToDate(DateUtil.fomatDate(passPO.getEndTime(),"HH:mm:ss"),"HH:mm:ss").getTime() ){
                    encriptValue.append(StringHandlerUtil.autlSupply(2,((Integer)(i+1)).toString(),"0"));
                    break;
                }
            }
            //备用字节
            encriptValue.append("0000");
            String des = DesEncryptUtil.getUserKey(encriptValue.toString(),encriptProjKey);
            String hex = des.substring(des.length()-6,des.length());
            hex=((Integer)Integer.parseInt(hex,16)).toString();
            password.append(hex.substring(hex.length()-4,hex.length()));
            if (valid != null && valid.getVisitorPassword() != null && 1 == valid.getVisitorPassword()){
                passPO.setPassword(password.toString());
            }else {
                passPO.setPassword("*******");
            }
            passPO.setType(DynamicPasswordTypeEnum.OFFLINE.getType());
        }
        String passNumber = RandomUtil.getRandomStringBySix(6);
        passPO.setPassNumber(passNumber);

        //生成访客单号二维码图片
        BufferedImage bimForVisitor = QrcodeUtils.getQR_CODEBufferedImage(passNumber, BarcodeFormat.QR_CODE, 300, 300, QrcodeUtils.getDecodeHintType());
        ByteArrayOutputStream outForVisitor = new ByteArrayOutputStream();
        ImageIO.write(bimForVisitor, "png", outForVisitor);
        InputStream inputForVisitor = new ByteArrayInputStream(outForVisitor.toByteArray());
        UploadFileUtil.UploadFile uploadFileUtilInfo = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                inputForVisitor,
                "png",
                FILE_ACCESS_URL,
                FileCatalogEnum.VISITOR_PASS_QRCODE_FILE.getType()
        );
        Map<String, Object> resultMapInfo = UploadFileUtil.uploadFile(uploadFileUtilInfo);
        Boolean returnCodeInfo = (Boolean)resultMapInfo.get("returnCode");
        if (returnCodeInfo == true){
            passPO.setPassQrCodeUrl(resultMapInfo.get("accessPath").toString());
        }
        iAppVisitorPassCodeRecordDao.update(SqlUtil.durableData(passPO, PlatformConstants.TABLE_UPDATE));

        //发送临时权限数据
        List<DeviceBusinessChangeLogPO> changes = new ArrayList<>();
        List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
        List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
        Map<String,Object> auth = new HashMap<>();
        auth.put("userId",passPO.getPassId());
        auth.put("projectId",passPO.getProjectId());
        auth.put("type",2);
        DeviceBusinessChangeLogPO po=new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_TEMP_AUTH,JsonUtil.toJSON(auth),passPO.getProjectId());
        changes.add(po);
        DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(passPO.getProjectId(),CloudElevatorChangeBusinessEnum.PUSH_TEMP_AUTH,JsonUtil.toJSON(auth));
        elevatorChanges.add(elevatorPo);
        DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(passPO.getProjectId(),CloudEntranceChangeBusinessEnum.PUSH_TEMP_AUTH, JsonUtil.toJSON(auth));
        entranceChanges.add(entrancePO);
        JSONObject dataJs = new JSONObject();
        dataJs.put("data",changes);
        //发送云对讲业务指令
        messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE, RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
        dataJs.put("data",elevatorChanges);
        //推送云电梯业务指令
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                JsonUtil.toJSON(dataJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
        //发送云门禁业务指令
        dataJs.put("data",entranceChanges);
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                JSON.toJSONString(dataJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
        );
        return passPO;
    }

}
